home *** CD-ROM | disk | FTP | other *** search
- /* PDlog Expand.c Derived from TN #95.
-
- Dave Hersey, Apple Developer Technical Support.
-
- 10/9/91… v1.0
- 2/25/92… v1.0.1 --> fixed lack of print handle tossing and added something to print. <dmh>
- 9/29/93… v1.0.2 --> fixed bug in Append_DITL (also in TN #95) which appends 2 extra bytes. <dmh>
- 6/20/95… v1.0.3 --> updated for Universal Headers and MWC-PPC <njvt>
- 11/16/95 v1.0.4 --> updated to use CallPItemProc() and PItemUPP. Make it fully ANSI.
- 6/10/96 v1.1 --> Use the OS's AppendDITL if it's there. Add balloon help.
-
- Explicitly include needed headers, so back-port to MPW is easier. <davep>
-
- NOTE: Apple reserves the top half of the screen (where the current DITL
- items are located). Applications may use the bottom half of the screen to
- add items, but should not change any items in the top half of the screen.
- An application should expand the print dialogs only as much as is
- absolutely necessary.
-
- A global search and replace of 'Job' with 'Stl' will produce code that
- modifies the style dialog.
-
-
- */
-
- #include <Printing.h>
- #include <Dialogs.h>
- #include <Gestalt.h>
- #include <MixedMode.h>
- #include <SegLoad.h>
- #include <Resources.h>
- #include <ToolUtils.h>
- #include <Fonts.h>
-
- static TPPrDlg PrtJobDialog; /* pointer to job dialog */
-
- /*
-
- This points to the following structure:
-
- struct TPrDlg {
- DialogRecord Dlg; // The Dialog window
- ModalFilterUPP pFltrProc; // The Filter Proc.
- PItemUPP pItemProc; // The Item evaluating proc.
- THPrint hPrintUsr; // The user's print record.
- Boolean fDoIt;
- Boolean fDone;
- long lUser1; // Four longs for apps to hang global data.
- long lUser2; // Plus more stuff needed by the particular
- long lUser3; // printing dialog.
- long lUser4;
- };
- typedef struct TPrDlg TPrDlg;
- typedef TPrDlg *TPPrDlg;
- typedef TPPrDlg TPPrDlgRef;
-
- */
-
- /* Declare ‘pascal’ functions and procedures */
-
- extern short Append_DITL(TPPrDlg, short); /* Our AppendDITL function. */
- extern pascal TPPrDlg MyJobDlgInit(THPrint); /* Our extention to PrJobInit. */
- extern pascal void MyJobItems(TPPrDlg, short); /* Our modal item handler. */
- extern OSErr Print(void);
-
- #define MyDITL 256 /* resource ID of my DITL to be spliced onto job dialog */
-
- THPrint hPrintRec; /* handle to print record */
- long prFirstItem; /* save our first item here */
- PItemUPP prPItemProc; /* we need to store the old itemProc here */
-
- /*-----------------------------------------------------------------------*/
- WindowPtr MyWindow;
- OSErr err;
- Str255 myStr;
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=mac68k
- #endif
-
- typedef struct dialog_item_struct {
- Handle handle; /* handle or procedure pointer for this item */
- Rect bounds; /* display rectangle for this item */
- char type; /* item type - 1 */
- char data[1]; /* length byte of data */
- } DialogItem, *DialogItemPtr, **DialogItemHandle;
-
- typedef struct append_item_list_struct {
- short max_index; /* number of items - 1 */
- DialogItem items[1]; /* first item in the array */
- } ItemList, *ItemListPtr, **ItemListHandle;
-
- typedef union signed_byte_union {
- short integer;
- char bytes[2];
- } ByteAccess;
-
-
- static Boolean append_exits(void);
- static Boolean append_exits(void)
- {
- long response;
-
- if (Gestalt(gestaltDITLExtAttr,&response) == noErr) {
- return !!(response & (1 << gestaltDITLExtPresent));
- } else {
- return false; /* simple-minded, but hey, so am I. -DaveP */
- }
- }
-
-
- /* This routine appends all of the items of a specified DITL */
- /* onto the end of a specified DLOG — We don’t even need to know the format */
- /* of the DLOG */
-
- /* this will be done in 3 steps: */
- /* 1. append the items of the specified DITL onto the existing DLOG */
- /* 2. expand the original dialog window as required */
- /* 3. return the adjusted number of the first new user item */
-
- short Append_DITL(TPPrDlg dialog, short item_list_ID)
- {
- ItemListHandle append_item_list; /* handle to DITL being appended */
- ItemListHandle dlg_item_list; /* handle to DLOG's item list */
- short first_item;
-
- dlg_item_list = (ItemListHandle)((DialogPeek)dialog)->items;
- first_item = (**dlg_item_list).max_index + 2;
-
- append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
- if ( append_item_list == NULL ) {
- DebugStr("\pError loading DITL resource");
- return first_item;
- }
-
- if (append_exits()) {
- AppendDITL((DialogPtr)dialog, (Handle) append_item_list, appendDITLBottom);
- return first_item;
- } else {
- Point offset;
- Rect max_rect;
- DialogItemPtr item; /* pointer to item being appended */
- short new_items, data_size, i;
- ByteAccess usb;
- OSErr err;
-
- /*
- Using the original DLOG
-
- 1. Remember the original window Size.
- 2. Set the offset Point to be the bottom of the original window.
- 3. Subtract 5 pixels from bottom and right, to be added
- back later after we have possibly expanded window.
- 4. Get working Handle to original item list.
- 5. Calculate our first item number to be returned to caller.
- 6. Get locked Handle to DITL to be appended.
- 7. Calculate count of new items.
- */
-
- if (dialog == NULL) ExitToShell();
-
- max_rect = ((DialogPeek)dialog)->window.port.portRect;
- offset.v = max_rect.bottom;
- offset.h = 0;
- max_rect.bottom -= 5;
- max_rect.right -= 5;
-
-
- HLock((Handle)append_item_list);
- new_items = (**append_item_list).max_index + 1;
-
- /*
- For each item,
- 1. Offset the rectangle to follow the original window.
- 2. Make the original window larger if necessary.
- 3. fill in item handle according to type.
- */
-
- item = (**append_item_list).items;
- for ( i = 0; i < new_items; i++ )
- {
- OffsetRect(&item->bounds, offset.h, offset.v);
- UnionRect(&item->bounds, &max_rect, &max_rect);
- usb.integer = 0;
- usb.bytes[1] = item->data[0];
-
- switch ( item->type & 0x7F )
- {
- case ctrlItem + btnCtrl :
- case ctrlItem + chkCtrl :
- case ctrlItem + radCtrl :
- item->handle = (Handle)NewControl((DialogPtr) dialog,
- &item->bounds, (StringPtr)item->data, true,
- 0, 0, 1, item->type & 0x03, 0);
- break;
-
- case ctrlItem + resCtrl :
- {
- item->handle = (Handle)GetNewControl(*(short*)(item->data + 1), (DialogPtr) dialog);
- (**(ControlHandle)item->handle).contrlRect = item->bounds;
- }
- break;
-
- case statText :
- case editText :
- err = PtrToHand(item->data + 1, &item->handle, usb.integer);
- break;
-
- case iconItem :
- item->handle = GetIcon(*(short*)(item->data + 1));
- break;
-
- case picItem :
- item->handle = (Handle)GetPicture(*(short*)(item->data + 1));
- break;
-
- default :
- item->handle = NULL;
- }
-
- data_size = (usb.integer + 1) & 0xFFFE;
- item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
- }
-
- /* We need to subtract the short below because otherwise the size of the DITL count
- ** gets factored in twice, and the resulting DTIL has two bytes of garbage appended
- ** to it. This is a problem with the original TN#95 code as well.
- */
-
- err = PtrAndHand((**append_item_list).items,
- (Handle)dlg_item_list,
- GetHandleSize((Handle) append_item_list)
- - sizeof(short));
-
- (**dlg_item_list).max_index += new_items;
- HUnlock((Handle) append_item_list);
- ReleaseResource((Handle) append_item_list);
-
- max_rect.bottom += 5;
- max_rect.right += 5;
- SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, true);
-
- return first_item;
- }
- }
-
-
- /*------------------------------------------------------------------------*/
-
- OSErr Print(void)
- {
- TPPrPort pPrPort;
- Rect aRect;
- TPrStatus theStatus;
-
-
- /* call PrJobInit to get pointer to the invisible job dialog */
- hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
- PrintDefault(hPrintRec);
- PrValidate(hPrintRec);
- if (PrError() != noErr)
- return PrError();
-
- PrtJobDialog = PrJobInit(hPrintRec);
-
- if (PrError() != noErr)
- return PrError();
-
- if (!PrDlgMain(hPrintRec, NewPDlgInitProc(MyJobDlgInit))) /* this line does all the stuff */
- return iPrAbort;
-
- if (PrError() != noErr)
- return PrError();
-
- pPrPort = PrOpenDoc(hPrintRec, NULL, NULL);
- PrOpenPage(pPrPort, NULL);
-
- aRect = (*hPrintRec)->prInfo.rPage;
- InsetRect(&aRect, 20, 20);
- PenSize(4, 4);
- FrameRect(&aRect);
-
- PrClosePage(pPrPort);
- PrCloseDoc(pPrPort);
-
- if (!PrError() && (*hPrintRec)->prJob.bJDocLoop == bSpoolLoop)
- PrPicFile(hPrintRec, NULL, NULL, NULL, &theStatus);
-
-
- /* that's all for now */
-
- if (hPrintRec) DisposeHandle((Handle) hPrintRec);
-
- return(noErr);
- } /* Print */
-
- /*------------------------------------------------------------------------*/
-
- pascal TPPrDlg MyJobDlgInit(THPrint hPrint)
- /*
- this routine appends items to the standard job dialog and sets up the
- user fields of the printing dialog record TPRDlg
-
- This routine will be called by PrDlgMain
- */
-
- {
- #pragma unused(hPrint)
-
- short firstItem; /* first new item number */
-
- short itemType, item;
- Handle itemH;
- Rect itemBox;
-
- firstItem = Append_DITL(PrtJobDialog, MyDITL); /*call routine to do this */
-
- prFirstItem = firstItem; /* save this so MyJobItems can find it */
-
- /* now we'll set up our DITL items -- The radio buttons */
-
- for (item = 5; item <= 7; item++)
- {
- GetDItem((DialogPtr) PrtJobDialog,firstItem + item -1,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH, (item == 5));
- }
-
- /* now we'll set up the second of our DITL items -- The checkbox */
-
- GetDItem((DialogPtr) PrtJobDialog,firstItem +2,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH,1);
-
- /*
- Now comes the part where we patch in our item handler. We have to save
- the old item handler address, so we can call it if one of the standard
- items is hit, and put our item handler's address in pItemProc field of
- the TPrDlg struct
- */
-
- prPItemProc = PrtJobDialog->pItemProc;
-
- /* Now we'll tell the modal item handler where our routine is */
- PrtJobDialog->pItemProc = NewPItemProc(MyJobItems) ;
-
-
- /* PrDlgMain expects a pointer to the modified dialog to be returned...*/
- return PrtJobDialog;
-
- } /*myJobDlgInit*/
-
- /*-----------------------------------------------------------------------*/
-
- static pascal Boolean testFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
- {
- #pragma unused(theDialog)
- #pragma unused(theEvent)
- #pragma unused(itemHit)
- // DebugStr("\pMy filter proc got called"); // This gets called a lot if you uncomment it
- return false;
- }
-
- static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo);
- static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo)
- {
- if (itemNo != 4) return;
- else {
- short oldFont = ((GrafPtr)theWindow)->txFont;
- short oldSize = ((GrafPtr)theWindow)->txSize;
- short itemType;
- Handle h;
- Rect r;
-
- SetPort(theWindow);
- TextFont(GetAppFont());
- TextSize(9);
- GetDialogItem((DialogPtr)theWindow,4,&itemType,&h,&r);
- MoveTo(r.left,r.bottom);
- DrawString("\p<http://www.winternet.com/~dask/poohsnif.html>");
- TextFont(oldFont);
- TextSize(oldSize);
- }
- }
-
- static void TestDialog(void);
- static void TestDialog(void)
- {
- DialogPtr theDialog = GetNewDialog(257,nil,(WindowPtr)-1L);
- short itemHit = 0;
- ModalFilterUPP mySubDialogFilterProc = nil; // NewModalFilterProc(testFilter); // for testing
- UserItemUPP mySubDialogUserProc = NewUserItemProc(testDialogUserItem);
-
- { // set up the user item
- short t;
- Handle h;
- Rect r;
-
- GetDialogItem(theDialog,4,&t,&h,&r);
- SetDialogItem(theDialog,4,t,(Handle)mySubDialogUserProc,&r);
- }
-
- SetDialogDefaultItem(theDialog,1);
- while(itemHit != 1) { // a WAY bad way of seeing if we're done, but I'm in a hurry
- ModalDialog(mySubDialogFilterProc, &itemHit);
- }
- DisposeDialog(theDialog);
- if (mySubDialogFilterProc != nil)
- DisposeRoutineDescriptor(mySubDialogFilterProc);
- if (mySubDialogUserProc != nil)
- DisposeRoutineDescriptor(mySubDialogUserProc);
- }
-
- /* here's the analogue to the SF dialog hook */
-
- pascal void MyJobItems( TPPrDlg theDialog, short itemNo )
- { /* MyJobItems */
- short myItem;
- short firstItem, item, itemType, theValue;
- Handle itemH;
- Rect itemBox;
-
- firstItem = prFirstItem; /* remember, we saved this in myJobDlgInit */
- // DebugStr("\p Looking at the item...");
- myItem = itemNo-firstItem+1; /* "localize" current item No */
- if (myItem > 0) /* if localized item > 0, it's one of ours */
- {
- /* find out which of our items was hit */
-
- switch (myItem)
- {
- case 1: /* Static text. */
- break;
- case 2: /* Edit text. */
- break;
- case 3: /* Check box. */
- GetDItem((DialogPtr) theDialog,firstItem +2,&itemType,&itemH,&itemBox);
- theValue = GetCtlValue((ControlHandle) itemH);
- SetCtlValue((ControlHandle) itemH, theValue != 1);
- break;
- case 4: /* Push button. */
- TestDialog();
- break;
- case 5: /* Radio buttons */
- case 6:
- case 7:
- for (item = 5; item <= 7; item++) {
- GetDItem((DialogPtr) theDialog,firstItem +item -1,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH, item == myItem);
- }
- break;
- case 8: /* Edit text. */
- break;
- default: Debugger(); /* OH OH */
- } /* switch */
- } /* if (myItem > 0) */
- else /* chain to standard item handler, whose address is saved in prPItemProc */
- {
- CallPItemProc(prPItemProc,(DialogPtr)theDialog, itemNo);
- }
- } /* MyJobItems */
-
-
- void main(void)
- {
- Rect myWRect;
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- InitDialogs((long)nil);
- InitCursor();
- SetRect(&myWRect,50,260,350,340);
-
- /* call the routine that does printing */
- PrOpen();
- err = Print();
-
- PrClose();
- } /* main */
-